/**  
 * <p>Title: OperaterExecutor.java</p>  
 * <p>Description: 算子执行器</p>  
 * <p>Copyright: Copyright (c) 2018</p>    
 * @author ji'anyuan  
 * @date 2018年3月10日  
 * @version 1.0  
 */
package org.mango.jiayin.operater.operater;

import java.util.HashMap;
import java.util.Map;

import org.mango.jiayin.operater.constants.Constants.Mark;
import org.mango.jiayin.operater.domain.EventData;
import org.mango.jiayin.operater.domain.OperaterDo;
import org.mango.jiayin.operater.exception.OperaterException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * <p>
 * Title: OperaterExecutor
 * </p>
 * <p>
 * Description: 算子执行器
 * </p>
 * 
 * @author ji'anyuan
 * @date 2018年3月10日
 */
public class OperaterExecutor {
	private static final Logger logger = LoggerFactory
			.getLogger(OperaterExecutor.class);

	/**
	 * 算子工厂
	 */
	private static OperaterFactory operaterFactory = OperaterFactory
			.getInstance();

	@SuppressWarnings("static-access")
	public static Object executor(OperaterDo opDo, EventData data) {
		if (data == null || opDo == null || "".equals(opDo.getOpName())) {
			throw new OperaterException("EventData is empty");
		}

		if (opDo == null || "".equals(opDo.getOpName())) {
			throw new OperaterException("OperaterDo is empty");
		}

		Operater operater = operaterFactory.getOperater(opDo.getOpName());

		if (operater == null) {
			throw new OperaterException("the " + opDo.getOpName()
					+ " is not support");
		}

		Map<String, Object> nestValues = null;
		String opParames = opDo.getOpParames();

		if (opDo.getNestedOp() != null) {
			OperaterDo nestedOp = opDo.getNestedOp();
			nestValues = new HashMap<String, Object>();
			Object value = executor(nestedOp, data);

			String opStr = nestedOp.getOpName() + Mark.leftPar
					+ nestedOp.getOpParames() + Mark.rightPar;

			opParames = opDo.getOpParames().replace(opStr, nestedOp.getId());

			nestValues.put(nestedOp.getId(), value);
		}
		logger.info("executor {}", new Object[] { opDo });
		return operater.calc(opParames.split(Mark.separate), data, nestValues);
	}
}
